package com.ssh.dao;

import java.io.Serializable;
import java.sql.SQLException;
import java.util.LinkedHashMap;
import java.util.List;

import javax.annotation.Resource;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.stereotype.Repository;

import com.ssh.core.QueryResult;

@Repository("commonDao")
public class CommonDao<T> extends HibernateDaoSupport {
	
	/**
	 * 将sessionFactory注入Spring的模板
	 */
	@Resource(name="sessionFactory")
	protected void setSF(SessionFactory sf) {
		setSessionFactory(sf);
	}
	
	public void save(T transientInstance) {
		getHibernateTemplate().save(transientInstance);
	}

	public void delete(T persistentInstance) {
		getHibernateTemplate().delete(persistentInstance);
	}
	
	public void delete(Class entityClass,Serializable id) {
		getHibernateTemplate().delete(load(entityClass,id));
		
	}

	public void update(T persistentInstance) {
		getHibernateTemplate().update(persistentInstance);
	}
	
	public void merge(T persistentInstance) {
		getHibernateTemplate().merge(persistentInstance);
	}
	
	public Object findById(Class entityClass,Serializable id) {
		return  getHibernateTemplate().get(entityClass.getName(), id);
	}
	public Object load(Class entityClass,Serializable id) {
		return getHibernateTemplate().load(entityClass, id);
	}

	public List<T> findByExample(T instance) {
		return getHibernateTemplate().findByExample(instance);
	}

	public List findByProperty(Class entityClass,String propertyName, Object value) {
		String queryString = "from "+ entityClass.getSimpleName() +" as model where model." + propertyName + "= ?";
		return getHibernateTemplate().find(queryString, value);
	}

	public List findAll(Class entityClass) {
		String queryString = "from " + entityClass.getSimpleName();
		return getHibernateTemplate().find(queryString);
	}
	
	
	public void execute(String hql) {
		final String hqlf=hql;
		getHibernateTemplate().execute(new HibernateCallback<T>(
				) {
					@Override
					public T doInHibernate(Session session)
							throws HibernateException, SQLException {
						session.createQuery(hqlf).executeUpdate();
						return null;
					}
		});
	}
	
	public List query(String sql) {
		final String sqlf=sql;
		return getHibernateTemplate().executeFind(new HibernateCallback(
				) {
			@Override
			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {
				return session.createSQLQuery(sqlf).list();
			}
		});
	}
	
	/**
	 * 指定过滤条件的分页数据
	 */
//	public QueryResult findScrollData(int start, int maxResults, List<String> whereClause){
//		return this.findScrollData(start, maxResults, whereClause, null);
//	}
//	/**
//	 * 无任何条件的分页
//	 */
//	public QueryResult findScrollData(int pageNo, int pageSize){
//		return this.findScrollData(pageNo, pageSize, null, null);
//	}
//	/**
//	 * 有排序规则的分页数据
//	 */
//	public QueryResult findScrollData(int pageNo, int pageSize, LinkedHashMap<String, String> orderbyClause) {
//		return this.findScrollData(pageNo, pageSize, null, orderbyClause);
//	}
	/**
	 * 分页查询数据
	 * @param start 开始记录
	 * @param end 结束记录
	 * @param whereClause 过滤条件
	 * @param orderbyClause 排序子句
	 * @return 查询结果， 里面包含了指定页的记录和总共的页数
	 */
	public QueryResult findScrollData(Class entityClass,int pageNo, int pageSize, List<String> whereClause, LinkedHashMap<String, String> orderbyClause) {
		int start = pageNo > 0 ?(pageNo - 1) * pageSize : 0;
		QueryResult qr = new QueryResult();
		Session session=getSession();
		Query q = session.createQuery("select count(*) from " + entityClass.getSimpleName() + " entity " + buildWhereClause(whereClause));
		
		int count = Integer.parseInt(q.uniqueResult() + "");
		if(start >= count) start = count - 1 - pageSize;
		q = session.createQuery("from " + entityClass.getSimpleName() + " entity " + buildWhereClause(whereClause) + buildOrderByClause(orderbyClause));
		
		q.setFirstResult(start).setMaxResults(pageSize);
		qr.setPageNo(pageNo).setPageSize(pageSize).setRecordCount(count).setRecords(q.list());
		releaseSession(session);
		return qr;
	}
	
	/**
	 * 带绑定查询的方法
	 * @param entityClass
	 * @param pageNo
	 * @param pageSize
	 * @param whereClause
	 * @param paramMap 绑定参数
	 * @param orderbyClause
	 * @return
	 */
	public QueryResult findScrollData(Class entityClass,int pageNo, int pageSize, List<String> whereClause, LinkedHashMap<String, String> paramMap,LinkedHashMap<String, String> orderbyClause) {
		int start = pageNo > 0 ?(pageNo - 1) * pageSize : 0;
		QueryResult qr = new QueryResult();
		Session session=getSession();
		Query q = session.createQuery("select count(*) from " + entityClass.getSimpleName() + " entity " + buildWhereClause(whereClause));
		setParameters(paramMap, q);
		
		int count = Integer.parseInt(q.uniqueResult() + "");
		if(start >= count) start = count - 1 - pageSize;
		q = session.createQuery("from " + entityClass.getSimpleName() + " entity " + buildWhereClause(whereClause) + buildOrderByClause(orderbyClause));
		setParameters(paramMap, q);
		
		q.setFirstResult(start).setMaxResults(pageSize);
		qr.setPageNo(pageNo).setPageSize(pageSize).setRecordCount(count).setRecords(q.list());
		releaseSession(session);
		return qr;
	}

	private Query setParameters(LinkedHashMap<String, String> paramMap, Query q) {
		if(paramMap!=null&&paramMap.size()>0){
			for(String key:paramMap.keySet()){
				q.setParameter(key, paramMap.get(key));
			}
		}
		return q;
	}
	
	/**
	 * 建立排序子句
	 */
	protected String buildOrderByClause(LinkedHashMap<String, String> orderbyClause) {
		StringBuilder orderby = new StringBuilder("");
		if(orderbyClause != null && orderbyClause.size() > 0) {
			orderby.append(" order by ");
			for(String prop : orderbyClause.keySet()) {
				orderby.append(" entity.").append(prop).append(" ").append(orderbyClause.get(prop)).append(",");
			}
			orderby.deleteCharAt(orderby.length()-1);
		}
		return orderby.toString();
	}
	
	/**
	 * 根据过滤条件收集器建立where子句
	 */
	protected String buildWhereClause(List<String> whereClause) {
		StringBuilder where = new StringBuilder("");
		if(whereClause != null && whereClause.size() > 0) {
			where.append(" ").append("where ");
			for(String str : whereClause) {
				where.append(" entity.").append(str).append(" and ");
			}
			where.delete(where.lastIndexOf("and"), where.length()-1);
		}
		return where.toString();
	}
}
